package com.uc.sdk.g3.handler;

import com.uc.sdk.g3.CMD;
import com.uc.sdk.utils.NumberUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.ScheduledFuture;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

public class HeartBeatHandler extends ChannelInboundHandlerAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(HeartBeatHandler.class);

    private static final String SEND_STR = "<?xml version=\"1.0\" encoding=\"gb2312\"?><xml><head>HEADINFO</head></xml>";


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        ping(ctx.channel());
    }

    final byte[] HB = new byte[]{(byte) 0xAA, (byte) 0x55, (byte) 0x00, (byte) 0xFF, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x4D, (byte) 0x0B, (byte) 0x3C, (byte) 0x3F, (byte) 0x78, (byte) 0x6D, (byte) 0x6C, (byte) 0x20, (byte) 0x76, (byte) 0x65, (byte) 0x72, (byte) 0x73, (byte) 0x69, (byte) 0x6F, (byte) 0x6E, (byte) 0x3D, (byte) 0x22, (byte) 0x31, (byte) 0x2E, (byte) 0x30, (byte) 0x22, (byte) 0x20, (byte) 0x65, (byte) 0x6E, (byte) 0x63, (byte) 0x6F, (byte) 0x64, (byte) 0x69, (byte) 0x6E, (byte) 0x67, (byte) 0x3D, (byte) 0x22, (byte) 0x67, (byte) 0x62, (byte) 0x32, (byte) 0x33, (byte) 0x31, (byte) 0x32, (byte) 0x22, (byte) 0x3F, (byte) 0x3E, (byte) 0x0D, (byte) 0x0A, (byte) 0x3C, (byte) 0x78, (byte) 0x6D, (byte) 0x6C, (byte) 0x3E, (byte) 0x0D, (byte) 0x0A, (byte) 0x3C, (byte) 0x68, (byte) 0x65, (byte) 0x61, (byte) 0x64, (byte) 0x3E, (byte) 0x48, (byte) 0x45, (byte) 0x41, (byte) 0x44, (byte) 0x49, (byte) 0x4E, (byte) 0x46, (byte) 0x4F, (byte) 0x3C, (byte) 0x2F, (byte) 0x68, (byte) 0x65, (byte) 0x61, (byte) 0x64, (byte) 0x3E, (byte) 0x0D, (byte) 0x0A, (byte) 0x3C, (byte) 0x2F, (byte) 0x78, (byte) 0x6D, (byte) 0x6C, (byte) 0x3E, (byte) 0x6D,};

    private ByteBuf make() {
        ByteBuf byteBuf = Unpooled.buffer();
//        byteBuf.writeBytes(CMD.HEADER);
//        byte[] content = SEND_STR.getBytes();
//        int length = content.length;
//        byte temp = 0x00;
//        byte[] lengthArr = NumberUtil.intToByte4HH(length);
//        temp = NumberUtil.xorCheck(lengthArr);
//        byteBuf.writeBytes(lengthArr);
//        byteBuf.writeByte(0x0B);
//        temp ^= 0x0B;
//        byteBuf.writeBytes(content);
//        temp ^= NumberUtil.xorCheck(content);
//        byteBuf.writeByte(temp);
        byteBuf.writeBytes(HB);
        return byteBuf;
    }

    private void ping(Channel channel) {
        int second = 5;
        LOGGER.debug("next heart beat will send after " + second + "s.");
        ScheduledFuture<?> future = channel.eventLoop().schedule(() -> {
            if (channel.isActive()) {
                channel.writeAndFlush(make());
            } else {
                channel.closeFuture();
                throw new RuntimeException();
            }
        }, second, TimeUnit.SECONDS);

        future.addListener((GenericFutureListener) future1 -> {
            if (future.isSuccess()) {
                ping(channel);
            }
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 当Channel已经断开的情况下, 仍然发送数据, 会抛异常, 该方法会被调用.
        cause.printStackTrace();
        ctx.close();
    }
}
